
#include "cmsis_os2.h"
#include "e53_medical_electrocardiogram.h"
#include "lz_hardware.h"
#include "los_task.h"


/*
    gpio_pwdn  GPIO0_PA5 ------ pw    ||  gpio_start GPIO0_PC7  ------ st
                         ------ clk   ||  cs         GPIO0_PB0  ------ cs
    mosi       GPIO0_PB2 ------ in    ||  clk        GPIO0_PB1  ------ scl
    miso       GPIO0_PB3 ------ out   ||  gpio_drdy  GPIO0_PC4  ------ dr

*/


#define ADS_ENABLE_SPI      1

#if ADS_ENABLE_SPI
#define ADS_SPI_BUS         1
SpiBusIo g_spi1m1 =
{
    .cs =   {.gpio = GPIO0_PB0, .func = MUX_GPIO,  .type = PULL_UP, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_OUT,  .val = LZGPIO_LEVEL_HIGH},
    .clk =  {.gpio = GPIO0_PB1, .func = MUX_FUNC4, .type = PULL_UP, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},
    .mosi = {.gpio = GPIO0_PB2, .func = MUX_FUNC4, .type = PULL_UP, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},
    .miso = {.gpio = GPIO0_PB3, .func = MUX_FUNC4, .type = PULL_UP, .drv = DRIVE_KEEP, .dir = LZGPIO_DIR_KEEP, .val = LZGPIO_LEVEL_KEEP},
    .id = FUNC_ID_SPI1,
    .mode = FUNC_MODE_M1,
};

LzSpiConfig g_spi1Conf = {.bitsPerWord = SPI_PERWORD_8BITS,
                          .firstBit = SPI_MSB,
                          .mode = SPI_MODE_1,
                          .csm = SPI_CMS_ONE_CYCLES,
                          .speed = 35000000,
                          .isSlave = false
                         };

#define CS_L                LzGpioSetVal(g_spi1m1.cs.gpio, LZGPIO_LEVEL_LOW)
#define CS_H                LzGpioSetVal(g_spi1m1.cs.gpio, LZGPIO_LEVEL_HIGH)

#else

#define CS_L                LzGpioSetVal(gpio_cs.gpio, LZGPIO_LEVEL_LOW)
#define CS_H                LzGpioSetVal(gpio_cs.gpio, LZGPIO_LEVEL_HIGH)

#define ADS_CLK_Clr()       LzGpioSetVal(gpio_sclk.gpio, LZGPIO_LEVEL_LOW)
#define ADS_CLK_Set()       LzGpioSetVal(gpio_sclk.gpio, LZGPIO_LEVEL_HIGH)

#define ADS_MOSI_Clr()      LzGpioSetVal(gpio_mosi.gpio, LZGPIO_LEVEL_LOW)
#define ADS_MOSI_Set()      LzGpioSetVal(gpio_mosi.gpio, LZGPIO_LEVEL_HIGH)

Pinctrl gpio_cs   =   {.gpio = GPIO0_PB0, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_sclk =   {.gpio = GPIO0_PB1, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_mosi =   {.gpio = GPIO0_PB2, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_miso =   {.gpio = GPIO0_PB3, .func = MUX_GPIO, .type = PULL_NONE, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_IN,  .val = LZGPIO_LEVEL_KEEP};

#endif

#define PWDN_L      LzGpioSetVal(gpio_pwdn.gpio, LZGPIO_LEVEL_LOW)
#define PWDN_H      LzGpioSetVal(gpio_pwdn.gpio, LZGPIO_LEVEL_HIGH)

#define START_L     LzGpioSetVal(gpio_start.gpio, LZGPIO_LEVEL_LOW)
#define START_H     LzGpioSetVal(gpio_start.gpio, LZGPIO_LEVEL_HIGH)

extern void Gpio_isr();

// Pinctrl gpio_drdy =   {.gpio = GPIO0_PA3, .func = MUX_GPIO, .type = PULL_UP,   .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_IN,  .val = LZGPIO_LEVEL_KEEP};
// Pinctrl gpio_start =  {.gpio = GPIO0_PA5, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
// Pinctrl gpio_pwdn =   {.gpio = GPIO0_PA0, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_drdy =   {.gpio = GPIO0_PC4, .func = MUX_GPIO, .type = PULL_UP,   .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_IN,  .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_start =  {.gpio = GPIO0_PC7, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};
Pinctrl gpio_pwdn =   {.gpio = GPIO0_PA5, .func = MUX_GPIO, .type = PULL_KEEP, .drv = DRIVE_LEVEL7, .dir = LZGPIO_DIR_OUT, .val = LZGPIO_LEVEL_KEEP};

uint8_t SPI1_Init()
{
#if ADS_ENABLE_SPI
    LzSpiDeinit(ADS_SPI_BUS);
    //初始化spi
    if (SpiIoInit(g_spi1m1) != LZ_HARDWARE_SUCCESS)
    {
        return LZ_HARDWARE_FAILURE;
    }
    if (LzSpiInit(ADS_SPI_BUS, g_spi1Conf) != LZ_HARDWARE_SUCCESS)
    {
        return LZ_HARDWARE_FAILURE;
    }
#else
    
    PinctrlSet(gpio_cs.gpio, gpio_cs.func, gpio_cs.type, gpio_cs.drv);
    LzGpioInit(gpio_cs.gpio);
    LzGpioSetDir(gpio_cs.gpio, gpio_cs.dir);
    LzGpioSetVal(gpio_cs.gpio, LZGPIO_LEVEL_HIGH);
    
    //SCLK
    PinctrlSet(gpio_sclk.gpio, gpio_sclk.func, gpio_sclk.type, gpio_sclk.drv);
    LzGpioInit(gpio_sclk.gpio);
    LzGpioSetDir(gpio_sclk.gpio, gpio_sclk.dir);
    LzGpioSetVal(gpio_sclk.gpio, LZGPIO_LEVEL_LOW);
    
    //MOSI
    PinctrlSet(gpio_mosi.gpio, gpio_mosi.func, gpio_mosi.type, gpio_mosi.drv);
    LzGpioInit(gpio_mosi.gpio);
    LzGpioSetDir(gpio_mosi.gpio, gpio_mosi.dir);
    LzGpioSetVal(gpio_mosi.gpio, LZGPIO_LEVEL_HIGH);
    
    //miso
    PinctrlSet(gpio_miso.gpio, gpio_miso.func, gpio_miso.type, gpio_miso.drv);
    LzGpioInit(gpio_miso.gpio);
    LzGpioSetDir(gpio_miso.gpio, gpio_miso.dir);
    
#endif
    //start
    PinctrlSet(gpio_start.gpio, gpio_start.func, gpio_start.type, gpio_start.drv);
    LzGpioInit(gpio_start.gpio);
    LzGpioSetDir(gpio_start.gpio, gpio_start.dir);
    
    //pwdn
    PinctrlSet(gpio_pwdn.gpio, gpio_pwdn.func, gpio_pwdn.type, gpio_pwdn.drv);
    LzGpioInit(gpio_pwdn.gpio);
    LzGpioSetDir(gpio_pwdn.gpio, gpio_pwdn.dir);
    
    //drdy
    PinctrlSet(gpio_drdy.gpio, gpio_drdy.func, gpio_drdy.type, gpio_drdy.drv);
    LzGpioInit(gpio_drdy.gpio);
    LzGpioSetDir(gpio_drdy.gpio, gpio_drdy.dir);
    LzGpioRegisterIsrFunc(gpio_drdy.gpio, LZGPIO_INT_EDGE_FALLING, Gpio_isr, NULL);
    return 0;
}

uint8_t SPI1_ReadWriteNByte(uint8_t *txData, uint8_t *rxData, uint32_t n)
{
#if ADS_ENABLE_SPI
    LzSpiWriteAndRead(ADS_SPI_BUS, 0, txData, rxData, n);
#else
    for (int i = 0; i < n; ++i)
    {
        rxData[i] = SPI1_ReadWriteByte(txData[i]);
    }
#endif
}

uint8_t SPI1_ReadWriteByte(uint8_t txData)
{
    uint8_t rxData = 0;
    
#if ADS_ENABLE_SPI
    LzSpiWriteAndRead(ADS_SPI_BUS, 0, &txData, &rxData, 1);
#else
    uint8_t i, val;
    for (i = 0; i < 8; i++)
    {
        ADS_CLK_Set();
        //数据发送
        if (txData & 0x80)
        {
            ADS_MOSI_Set();
            // ToyUdelay(1);
        }
        else
        {
            ADS_MOSI_Clr() ;
            //ToyUdelay(1);
        }
        txData <<= 1;
        ToyUdelay(1);
        ADS_CLK_Clr();
        rxData <<= 1;
        LzGpioGetVal(gpio_miso.gpio, &val);
        //ToyUdelay(1);
        if (val)
        {
            rxData++;
            ToyUdelay(1);
        }
    }
#endif
    return rxData;
}



void ADS1292_Write_Reg(unsigned char addr, unsigned char data)
{
    CS_L;                        // 片选拉低
    ToyUdelay(10);
    SPI1_ReadWriteByte(addr);    // 包含命令操作码和寄存器地址
    ToyUdelay(10);
    SPI1_ReadWriteByte(0x00);    // 要读取的寄存器数+1
    ToyUdelay(10);
    SPI1_ReadWriteByte(data);    // 写入的数据
    ToyUdelay(10);
    CS_H;                        // 片选置高
}


unsigned char ADS1292_Read_Reg(unsigned char addr)
{
    unsigned char Rxdata;
    CS_L;                                 // 片选拉低
    ToyUdelay(10);
    SPI1_ReadWriteByte(addr);             // 包含命令操作码和寄存器地址
    ToyUdelay(10);
    SPI1_ReadWriteByte(0x00);             // 要读取的寄存器数+1
    ToyUdelay(10);
    Rxdata = SPI1_ReadWriteByte(0xFF);    // 读取的数据
    ToyUdelay(10);
    CS_H;                                 // 片选置高
    return Rxdata;
}

void ADS1292_PowerOnInit(void)
{
    unsigned char device_id;
    
    START_H;
    CS_H;
    PWDN_L; // 进入掉电模式
    LOS_Msleep(1000);
    PWDN_H; // 退出掉电模式
    LOS_Msleep(500);   // 等待稳定
    PWDN_L; // 发出复位脉冲
    ToyUdelay(10);
    PWDN_H;
    LOS_Msleep(1000); // 等待稳定，可以开始使用ADS1292R
    
    START_L;
    CS_L;
    ToyUdelay(10);
    SPI1_ReadWriteByte(SDATAC); // 发送停止连续读取数据命令
    ToyUdelay(10);
    CS_H;
    
    int cnt  = 5;
    //获取芯片ID
    device_id = ADS1292_Read_Reg(RREG | ID);
    while (device_id != 0x73 && cnt-- > 0)
    {
        printf("ERROR ID:%02x\r\n", device_id);
        device_id = ADS1292_Read_Reg(RREG | ID);
        LOS_Msleep(100);
    }
    printf("ID:%02x\r\n", device_id);
    
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | CONFIG2,  0XE0); // 使用内部参考电压
    LOS_Msleep(10);                           // 等待内部参考电压稳定
    ADS1292_Write_Reg(WREG | CONFIG1,  0X01); // 设置转换速率为500SPS
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | LOFF,     0XF0); // 该寄存器配置引出检测操作
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | CH1SET,   0X00); // 增益6，连接到电极
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | CH2SET,   0X00); // 增益6，连接到电极
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | RLD_SENS, 0xEF);
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | LOFF_SENS, 0x0F);
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | LOFF_STAT, 0x00);
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | RESP1,    0xEA); // 开启呼吸检测（ADS1292R特有）
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | RESP2,    0x03);
    ToyUdelay(10);
    ADS1292_Write_Reg(WREG | GPIO,     0x0C);
    ToyUdelay(10);
    CS_L;
    ToyUdelay(10);
    SPI1_ReadWriteByte(RDATAC);        // 发送启动连续读取数据命令
    ToyUdelay(10);
    CS_H;
    CS_L;
    START_H;                           // 启动转换
    LzGpioEnableIsr(gpio_drdy.gpio);
}

/***************************************************************
* 函数名称: e53_em_init
* 说    明: E53_Em初始化
* 参    数: uint32_t args
* 返 回 值: 无
***************************************************************/
void e53_em_init(uint32_t args)
{
    e53_em_deinit();
    SPI1_Init();           // SPI1和其他io初始化
    ADS1292_PowerOnInit(); // ADS1292上电初始化
}

void e53_em_deinit(void)
{
    printf("e53_em_deinit\n");
    LzGpioDisableIsr(gpio_drdy.gpio);
    LzGpioDeinit(gpio_drdy.gpio);
    LzGpioDeinit(gpio_start.gpio);
    LzGpioDeinit(gpio_pwdn.gpio);
    
#if ADS_ENABLE_SPI
    LzSpiDeinit(ADS_SPI_BUS);
    LzGpioDeinit(g_spi1m1.cs.gpio);
    LzGpioDeinit(g_spi1m1.clk.gpio);
    LzGpioDeinit(g_spi1m1.miso.gpio);
    LzGpioDeinit(g_spi1m1.mosi.gpio);
#else
    LzGpioDeinit(gpio_cs.gpio);
    LzGpioDeinit(gpio_sclk.gpio);
    LzGpioDeinit(gpio_mosi.gpio);
    LzGpioDeinit(gpio_miso.gpio);
#endif
}
